﻿using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Windows;
using System.Windows.Input;
using System.Xml.Linq;
using ToDoListReminder.Data;

namespace ToDoListReminder.ViewModel
{
	/// <summary>
	/// The main window view model.
	/// </summary>
	public class MainWindowView
	{
		#region Fields

		/// <summary>
		/// Holds the command about.
		/// </summary>
		private EditionCommand commandAbout_;

		/// <summary>
		/// Holds the command config.
		/// </summary>
		private EditionCommand commandConfig_;

		/// <summary>
		/// Holds the command refresh.
		/// </summary>
		private EditionCommand commandRefresh_;

		/// <summary>
		/// Holds the command exit.
		/// </summary>
		private EditionCommand commandExit_;

		/// <summary>
		/// Holds the window reference.
		/// </summary>
		private readonly Window window_;

		/// <summary>
		/// Holds the task list.
		/// </summary>
		private ObservableCollection<Task> tasks_;

		/// <summary>
		/// Holds the total projects count.
		/// </summary>
		private int projectCount_;

		/// <summary>
		/// Holds the total task count.
		/// </summary>
		private int taskCount_;

		#endregion

		#region Properties

		/// <summary>
		/// Gets the command about.
		/// </summary>
		public ICommand CommandAbout
		{
			get
			{
				if (commandAbout_ == null)
				{
					commandAbout_ = new EditionCommand();
					commandAbout_.OnCanExecute += CommandAboutOnCanExecute;
					commandAbout_.OnExecute += CommandAboutOnExecute;
				}

				return commandAbout_;
			}
		}

		/// <summary>
		/// Gets the command config.
		/// </summary>
		public ICommand CommandConfig
		{
			get
			{
				if (commandConfig_ == null)
				{
					commandConfig_ = new EditionCommand();
					commandConfig_.OnCanExecute += CommandConfigOnCanExecute;
					commandConfig_.OnExecute += CommandConfigOnExecute;
				}

				return commandConfig_;
			}
		}

		/// <summary>
		/// Gets the command refresh.
		/// </summary>
		public ICommand CommandRefresh
		{
			get
			{
				if (commandRefresh_ == null)
				{
					commandRefresh_ = new EditionCommand();
					commandRefresh_.OnCanExecute += CommandRefreshOnCanExecute;
					commandRefresh_.OnExecute += CommandRefreshOnExecute;
				}

				return commandRefresh_;
			}
		}

		/// <summary>
		/// Gets the command exit.
		/// </summary>
		public ICommand CommandExit
		{
			get
			{
				if (commandExit_ == null)
				{
					commandExit_ = new EditionCommand();
					commandExit_.OnCanExecute += CommandExitOnCanExecute;
					commandExit_.OnExecute += CommandExitOnExecute;
				}

				return commandExit_;
			}
		}

		/// <summary>
		/// Gets or sets the config data.
		/// </summary>
		public Config Config
		{
			get;
			set;
		}

		/// <summary>
		/// Gets the task list.
		/// </summary>
		public ObservableCollection<Task> Tasks
		{
			get
			{
				if (tasks_ == null)
				{
					tasks_ = new ObservableCollection<Task>();
				}
				return tasks_;
			}
		}


		/// <summary>
		/// Gets or sets the Status.
		/// </summary>
		public Status Status
		{
			get;
			set;
		}

		#endregion

		#region Constructors

		/// <summary>
		/// Initializes a new instance of the MainWindowView class.
		/// </summary>
		/// <param name="window"></param>
		public MainWindowView(Window window)
		{
			window_ = window;
			Status = new Status();
			Config = new Config();
			Config.LoadData();
			FillProjects();
		}

		#endregion

		#region Methods

		/// <summary>
		/// Executes the command about.
		/// </summary>
		/// <param name="parameter">The command data.</param>
		private void CommandAboutOnExecute(object parameter)
		{
			var aboutWindow = new AboutWindow
			{
				Owner = window_
			};


			aboutWindow.ShowDialog();
		}

		/// <summary>
		/// Checks, if the command about may be executed.
		/// </summary>
		/// <param name="parameter">The command data.</param>
		/// <returns>True, if the command may be executed.</returns>
		private static bool CommandAboutOnCanExecute(object parameter)
		{
			return true;
		}

		/// <summary>
		/// Executes the command config.
		/// </summary>
		/// <param name="parameter">The command data.</param>
		private void CommandConfigOnExecute(object parameter)
		{
			var configWindow = new ConfigWindow(Config)
			{
				Owner = window_
			};

			Config.BeginEdit();
			if (!(bool)configWindow.ShowDialog())
			{
				Config.CancelEdit();
			}
			else
			{
				FillProjects();
			}
		}

		/// <summary>
		/// Checks, if the command config may be executed.
		/// </summary>
		/// <param name="parameter">The command data.</param>
		/// <returns>True, if the command may be executed.</returns>
		private static bool CommandConfigOnCanExecute(object parameter)
		{
			return true;
		}

		/// <summary>
		/// Executes the command refresh.
		/// </summary>
		/// <param name="parameter">The command data.</param>
		private void CommandRefreshOnExecute(object parameter)
		{
			FillProjects();
		}

		/// <summary>
		/// Checks, if the command refresh may be executed.
		/// </summary>
		/// <param name="parameter">The command data.</param>
		/// <returns>True, if the command may be executed.</returns>
		private static bool CommandRefreshOnCanExecute(object parameter)
		{
			return true;
		}

		/// <summary>
		/// Executes the command exit.
		/// </summary>
		/// <param name="parameter">The command data.</param>
		private void CommandExitOnExecute(object parameter)
		{
			Config.SaveData();
			window_.Close();
		}

		/// <summary>
		/// Checks, if the command exit may be executed.
		/// </summary>
		/// <param name="parameter">The command data.</param>
		/// <returns>True, if the command may be executed.</returns>
		private static bool CommandExitOnCanExecute(object parameter)
		{
			return true;
		}

		/// <summary>
		/// Fills projects.
		/// </summary>
		/// <remarks>calls the FillTasks for each project.</remarks>
		private void FillProjects()
		{
			// Initialize.
			Tasks.Clear();
			projectCount_ = Config.Projects.Count;
			taskCount_ = 0;

			// Filling.
			foreach (var project in Config.Projects)
			{
				if (!String.IsNullOrEmpty(project.FileName))
				{
					try
					{
						var rootElement = XElement.Load(project.FileName);
						var projectName = Path.GetFileNameWithoutExtension(project.FileName);

						FillTasks(rootElement, projectName);
					}
					catch
					{
					}
				}
			}

			Status.Projects = String.Format("{0} projects", projectCount_);
			Status.Tasks = String.Format("{0} tasks", taskCount_);
		}

		/// <summary>
		/// Fills the task list.
		/// </summary>
		/// <param name="parentTaslElement">The parent element.</param>
		/// <param name="projectName">The project name.</param>
		private void FillTasks(XContainer parentTaslElement, string projectName)
		{
			foreach (var taskElement in parentTaslElement.Elements("TASK"))
			{
				if (taskElement.Element("TASK") != null)
				{
					FillTasks(taskElement, projectName);
				}
				else
				{
					if (taskElement.Attribute("DONEDATE") == null)
					{
						if (taskElement.Attribute("TITLE") != null
							&& taskElement.Attribute("TITLE").Value != null)
						{
							Tasks.Add(new Task(projectName, taskElement.Attribute("TITLE").Value));
							++taskCount_;
						}
					}
				}
			}
		}

		#endregion

	}
}
